package main

import "fmt"

//	type Animal interface {
//		Talk()
//		Eat()
//		Name() string
//	}
//
// type Dog struct {
// }
//
//	func (d Dog) Talk() {
//		fmt.Println("汪汪汪")
//	}
//
//	func (d Dog) Eat() {
//		fmt.Println("我在吃骨头")
//	}
//
//	func (d Dog) Name() string {
//		fmt.Println("我的名字叫旺财")
//		return "旺财"
//	}
//
//	func main() {
//		var a Animal
//		var d Dog
//		a = d
//		a.Eat()
//		fmt.Printf("%T %v\n", a, a)
//		/*
//			指针类型是没有实现 Eat 值类型这个接口的，
//			那么接口里面进行一个转换。
//			首先取出地址  &Dog，然后对地址取值 *(&Dog) 就变成值类型了，
//			值类型就实现了 Eat 这个方法，所以就调用了。
//		*/
//		var d1 *Dog = &Dog{}
//		a = *d1
//		a.Eat()
//		fmt.Printf("*Dog %T %v", a, a)
//	}
type Animal interface {
	Talk()
	Eat()
	Name() string
}

type Dog struct {
}

func (d Dog) Talk() {
	fmt.Println("汪汪汪")
}

func (d Dog) Eat() {
	fmt.Println("我在吃骨头")
}

func (d *Dog) Name() string {
	fmt.Println("我的名字叫旺财")
	return "旺财"
}
func main() {
	var a Animal
	var d Dog
	/*
		a 存的是是一个值类型的 Dog，那么调用 a.Eat(),首先要去去 &Dog->Eat()
		如果一个变量存储在接口类型的变量中之后，那么不能获取这个变量的地址。
	*/
	// a = d// 这样是存不进去的。
	a = &d
	a.Eat()

	fmt.Printf("%T %v\n", a, a)
	var d1 *Dog = &Dog{}
	//即使 Eat() 方法使用值接收器，你也可以将指向 Dog 实例的指针赋值给 Animal 类型的变量 a。
	//在调用 Eat() 方法时，Go 会自动解引用 a 中的指针，得到 Dog 的值，然后调用方法。
	a = d1
	a.Eat()
	fmt.Printf("*Dog %T %v", a, a)

}
